#!/usr/bin/env ruby

# Copyright (c) 2010-2012 Microsoft Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#	http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require 'rubygems'
require 'ruby-aws'
require 'facets/array'
require './include/array'

module MOS

def parseAnswer(answer_xml)
	answer = { }

	xml_doc = REXML::Document.new(answer_xml)
	xml_doc.root.each_element('//Answer') do |a|
		key = a.elements['QuestionIdentifier'].text.to_sym

		if a.elements['SelectionIdentifier'] != nil
			value = a.elements['SelectionIdentifier'].text.to_s
		elsif a.elements['OtherSelectionText'] != nil
			value = a.elements['OtherSelectionText'].text.to_s
		elsif a.elements['FreeText'] != nil
			value = a.elements['FreeText'].text.to_s
		else
			value = ''
		end

		# replace tabs and quotes, because the answer with be saved in tabular format
		value.gsub!(/[\t"]/, ' ')

		# if value is a number, cast it
		if value =~ /^[-+]?[0-9]*\.?[0-9]+$/
			value = value.to_f
		end

		# if value is of the form "number | ... | number", cast it to the mean value and print a warning
		if value =~ /^([-+]?[0-9]*\.?[0-9]+)(\|[-+]?[0-9]*\.?[0-9]+)+$/
			value_array = value

			value = value.split('|')
			value = value.map { |v| v.to_f }
			value = value.mean

			puts "Warning: retrieved score '#{value_array}' (HIT has multiple copies of the same file?)."
			puts "Converted #{value_array} to #{value.to_s}."
		end

		answer[key] = value
	end

	answer
end

def indexByInteger(input, key)
	output = []
	input.each_pair do |val, h|
		h = h.clone
		h[key] = val
		output << h
	end
	output
end

def indexByUniqueKey(input, key)
	output = { }
	input.each do |item|
		item = item.clone
		val  = item.delete(key).to_sym
		output[val] = item
	end
	output
end

def indexByNonUniqueKey(input, key)
	output = { }
	input.each do |item|
		item = item.clone
		val  = item.delete(key).to_sym
		(output[val] ||= []) << item
	end
	output
end

# Builds a question template suitable for parameter instantiation with Amazon's Binder class.
# Appends the 'header' with 'count' copies of 'question', followed by the 'footer'.
#
# Every <%= @field %> entry in the question is replaced with <%= @fieldI %>, where 1 <= I <= count
def buildQuestionTemplate(header, question, footer, count)
	template = header
	for i in (1..count)
		template << question.gsub(/<%=\s+@(\w+)\s+%>/) { |match| "<%= @#{$1.to_s + i.to_s} %>" }
	end
	template << footer
end

def buildQuestionTemplateExternal(question_url, count)
	external_url = question_url + '?reference_URL=<%= @reference_URL %>&amp;'
	for i in 1..count do
		external_url << "identifier<%= @index#{i} %>=<%= @identifier#{i} %>"
		external_url << '&amp;'
		external_url << "url<%= @index#{i} %>=<%= @URL#{i} %>"
		external_url << '&amp;' if i < count
	end

	template = <<END
<?xml version="1.0"?>
<ExternalQuestion xmlns="http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2006-07-14/ExternalQuestion.xsd">
	<ExternalURL>#{external_url}</ExternalURL>
	<FrameHeight>800</FrameHeight>
</ExternalQuestion>
END

	template
end

def buildInputDataSet(input, shuffle=true)
	input = input.clone
	input.shuffle! if shuffle

	dataset = { }
	input.each_index do |i|
		input[i].each_pair { |key,val| dataset[(key.to_s + (i+1).to_s).to_sym] = val }
		dataset[('index' + (i+1).to_s).to_sym] = (i+1).to_s
	end
	dataset
end

module_function :parseAnswer
module_function :indexByInteger
module_function :indexByUniqueKey
module_function :indexByNonUniqueKey
module_function :buildQuestionTemplate
module_function :buildQuestionTemplateExternal
module_function :buildInputDataSet

end # MOS
